/************************************************
info: 主要处理特定格式的json数据的解析，打印对应字段
	  练习json字符串的使用，构造json和解析json
data: 2022/02/10
author: hlp
************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"

void vps_parse_json();
//构造json字符串  返回构造的json字符串
char * make_json_str();
//解析构造的json字符串
int parse_json_str(const char * jsonstr);

int main()
{
	//测试一下使用cjson解析
	vps_parse_json();
	//构造json字符串  内部会对json字符串申请内存 要释放
	char * strjson = make_json_str();
	//解析构造的json字符串 打印对应的字段
	parse_json_str(strjson);
	free(strjson);
	return 0;
}


//测试对json字符串的解析
void vps_parse_json()
{
	const char * client_json_data = "{\"DNIS\":\"dnis\" , \"ACDGroup\":\"ACDGroup\" ,\"TrunkNo\":\"TrunkNo\" ,\"ExtNo\":\"ExtNo\" ,\
\"CallerNo\":\"CallerNo\" ,\"CalledPartyNo\":\"CalledPartyNo\" , \"CallMark\":\"CallMark\" ,\"UniqueCallID\":\"UniqueCallID\" ,\
\"IncidentNo\":\"IncidentNo\" , \"StationOrDepot\":\"StationOrDepot\" ,\"OperatorID\":\"OperatorID\" ,\
\"WorkstationNo\":\"WorkstationNo\" , \"CallerVehicleID\":\"CallerVehicleID\" ,\"GSSI\":\"GSSI\" ,\"GSSI\":\"GSSI\" ,\
\"ResourceStatus\":\"ResourceStatus\" ,\"OicOrOfficerID\":\"OicOrOfficerID\" ,\"ISSI\":\"ISSI\" , \"CalledSSI\":\"CalledSSI\" ,\
\"CallType\":\"CallType\" ,\"FileLink\":\"FileLink\" , \"SenderDeviceID\":\"SenderDeviceID\" ,\"HKPFRN\":\"HKPFRN\" ,\
\"SourceType\":\"SourceType\" ,\"RecorderNo\":\"RecorderNo\"}";
	cJSON *root = cJSON_Parse(client_json_data);
	if(root == NULL)
	{
		printf("vps json str to json error \n");
		return ;
	}
	cJSON *DNIS = cJSON_GetObjectItem(root, "DNIS");
	printf(" vps DNIS is:[%s] \n", DNIS->valuestring);
	cJSON *ACDGroup = cJSON_GetObjectItem(root, "ACDGroup");
	printf(" vps ACDGroup is:[%s] \n", ACDGroup->valuestring);
	cJSON *TrunkNo = cJSON_GetObjectItem(root, "TrunkNo");
	printf(" vps TrunkNo is:[%s] \n", TrunkNo->valuestring);
	cJSON *ExtNo = cJSON_GetObjectItem(root, "ExtNo");
	printf(" vps ExtNo is:[%s] \n", ExtNo->valuestring);
	cJSON *CallerNo = cJSON_GetObjectItem(root, "CallerNo");
	printf(" vps CallerNo is:[%s] \n", CallerNo->valuestring);
	cJSON *CalledPartyNo = cJSON_GetObjectItem(root, "CalledPartyNo");
	printf(" vps CalledPartyNo is:[%s] \n", CalledPartyNo->valuestring);
	cJSON *CallMark = cJSON_GetObjectItem(root, "CallMark");
	printf(" vps CallMark is:[%s] \n", CallMark->valuestring);
	cJSON *UniqueCallID = cJSON_GetObjectItem(root, "UniqueCallID");
	printf(" vps UniqueCallID is:[%s] \n", UniqueCallID->valuestring);
	cJSON *IncidentNo = cJSON_GetObjectItem(root, "IncidentNo");
	printf(" vps IncidentNo is:[%s] \n", IncidentNo->valuestring);
	cJSON *StationOrDepot = cJSON_GetObjectItem(root, "StationOrDepot");
	printf(" vps StationOrDepot is:[%s] \n", StationOrDepot->valuestring);
	cJSON *OperatorID = cJSON_GetObjectItem(root, "OperatorID");
	printf(" vps OperatorID is:[%s] \n", OperatorID->valuestring);
	cJSON *WorkstationNo = cJSON_GetObjectItem(root, "WorkstationNo");
	printf(" vps WorkstationNo is:[%s] \n", WorkstationNo->valuestring);
	cJSON *CallerVehicleID = cJSON_GetObjectItem(root, "CallerVehicleID");
	printf(" vps CallerVehicleID is:[%s] \n", CallerVehicleID->valuestring);
	cJSON *GSSI = cJSON_GetObjectItem(root, "GSSI");
	printf(" vps GSSI is:[%s] \n", GSSI->valuestring);
	cJSON *ResourceStatus = cJSON_GetObjectItem(root, "ResourceStatus");
	printf(" vps ResourceStatus is:[%s] \n", ResourceStatus->valuestring);
	cJSON *OicOrOfficerID = cJSON_GetObjectItem(root, "OicOrOfficerID");
	printf(" vps OicOrOfficerID is:[%s] \n", OicOrOfficerID->valuestring);
	cJSON *ISSI = cJSON_GetObjectItem(root, "ISSI");
	printf(" vps ISSI is:[%s] \n", ISSI->valuestring);
	cJSON *CalledSSI = cJSON_GetObjectItem(root, "CalledSSI");
	printf(" vps CalledSSI is:[%s] \n", CalledSSI->valuestring);
	cJSON *CallType = cJSON_GetObjectItem(root, "CallType");
	printf(" vps CallType is:[%s] \n", CallType->valuestring);
	cJSON *FileLink = cJSON_GetObjectItem(root, "FileLink");
	printf(" vps FileLink is:[%s] \n", FileLink->valuestring);
	cJSON *SenderDeviceID = cJSON_GetObjectItem(root, "SenderDeviceID");
	printf(" vps SenderDeviceID is:[%s] \n", SenderDeviceID->valuestring);
	cJSON *HKPFRN = cJSON_GetObjectItem(root, "HKPFRN");
	printf(" vps HKPFRN is:[%s] \n", HKPFRN->valuestring);
	cJSON *SourceType = cJSON_GetObjectItem(root, "SourceType");
	printf(" vps SourceType is:[%s] \n", SourceType->valuestring);
	cJSON *RecorderNo = cJSON_GetObjectItem(root, "RecorderNo");
	printf(" vps RecorderNo is:[%s] \n", RecorderNo->valuestring);

	if(root != NULL)
	{
		printf("\njson delete success \n");
		cJSON_Delete(root);
	}

}
/*********************
{
	"name":	"test",
	"age":	80,
	"languages":	["C++", "Java"],
	"phone":	{
		"number":	"1867216i144",
		"type":	"home"
	},
	"languages":	[{
			"name":	"Linux kernel development",
			"price":	"7.7"
		}, {
			"name":	"Linux server development",
			"price":	"8.0"
		}],
	"vip":	true,
	"address":	""
}
*********************/
 char * make_json_str()
 {
 	// 创建json对象
    cJSON *root = cJSON_CreateObject();
    // 添加键值对
    cJSON_AddItemToObject(root, "name", cJSON_CreateString("test"));
    cJSON_AddItemToObject(root, "age", cJSON_CreateNumber(80));
    // 创建json数组
    cJSON *languages = cJSON_CreateArray();
    cJSON_AddItemToArray(languages, cJSON_CreateString("C++"));
    cJSON_AddItemToArray(languages, cJSON_CreateString("Java"));
    cJSON_AddItemToObject(root, "languages", languages);

    cJSON *phone = cJSON_CreateObject();
    cJSON_AddItemToObject(phone, "number", cJSON_CreateString("1867216i144"));
    cJSON_AddItemToObject(phone, "type", cJSON_CreateString("home"));
    cJSON_AddItemToObject(root, "phone", phone);

    cJSON *book0 = cJSON_CreateObject();
    cJSON_AddItemToObject(book0, "name", cJSON_CreateString("Linux kernel development"));
    cJSON_AddItemToObject(book0, "price", cJSON_CreateNumber(7.7));
    cJSON *book1 = cJSON_CreateObject();
    cJSON_AddItemToObject(book1, "name", cJSON_CreateString("Linux server development"));
    cJSON_AddItemToObject(book1, "price", cJSON_CreateNumber(8.0));
    // 创建json数组
    cJSON *books = cJSON_CreateArray();
    cJSON_AddItemToArray(books, book0);
    cJSON_AddItemToArray(books, book1);
    cJSON_AddItemToObject(root, "books", books);

    cJSON_AddItemToObject(root, "vip", cJSON_CreateBool(1));
    cJSON_AddItemToObject(root, "address", cJSON_CreateString("")); // NULL值的问题

    //格式化json对象 并返回
    char *jsonstr = cJSON_Print(root);
    //注意释放 内部会释放其子节点的
    cJSON_Delete(root);

    printf("make json str is [%lu][%s] \n", strlen(jsonstr), jsonstr);
    return jsonstr;
 }

void printCJson(cJSON *root);
int parse_json_str(const char * jsonstr)
{
	if(jsonstr == NULL)
	{
		printf("parse json error: jsonstr is null \n");
		return -1;
	}
	cJSON *root = cJSON_Parse(jsonstr);
	if(root == NULL)
	{
		printf("parse json error: cJSON_Parse error \n");
		return -1;
	}
	//获取对应的字段并进行打印
	printCJson(root);
	cJSON_Delete(root);
    return 0;
}

void printCJson(cJSON *root)
{
	//获取到各个子对象
	cJSON *name = cJSON_GetObjectItem(root, "name");
    cJSON *age = cJSON_GetObjectItem(root, "age");
    cJSON *languages = cJSON_GetObjectItem(root, "languages");
    cJSON *phone = cJSON_GetObjectItem(root, "phone");
    cJSON *books = cJSON_GetObjectItem(root, "books");
    cJSON *vip = cJSON_GetObjectItem(root, "vip");
    cJSON *address = cJSON_GetObjectItem(root, "address");

    printf(" name: %s\n", name->valuestring);
    printf(" age: %d\n", age->valueint);
    printf(" languages: ");
    for (int i = 0; i < cJSON_GetArraySize(languages); i++)
    {
        cJSON *lang = cJSON_GetArrayItem(languages, i);
        if (i != 0)
        {
            printf(", ");
        }
        printf("%s", lang->valuestring);
    }
    printf("\n");

    cJSON *number = cJSON_GetObjectItem(phone, "number");
    cJSON *type = cJSON_GetObjectItem(phone, "type");
    printf(" phone number: %s, type: %s\n", number->valuestring, type->valuestring);

    for (int i = 0; i < cJSON_GetArraySize(books); i++)
    {
        cJSON *book = cJSON_GetArrayItem(books, i);
        cJSON *name = cJSON_GetObjectItem(book, "name");
        cJSON *price = cJSON_GetObjectItem(book, "price");
        printf(" book name: %s, price: %lf\n", name->valuestring, price->valuedouble);
    }

    printf(" vip: %d\n", vip->valueint);
    if (address && !cJSON_IsNull(address))
    {
        printf(" address: %s\n", address->valuestring);
    }
    else
    {
        printf(" address is null\n");
    }
}